#!/usr/bin/python
# -*- coding: utf-8 -*-

#This file is part of pyLot library.
#
# pyLot is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyLot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pyLot.  If not, see <http://www.gnu.org/licenses/>.

__author__ = u'Pierre Puiseux, Guillaume Baty'
__copyright__ = u"Copyright 2011-2012 (C) andheo, Université de Pau et des Pays de l'Adour"
__credits__ = [u'Pierre Puiseux', u'Guillaume Baty']
__license__ = "GNU Lesser General Public License"

import sys

class pyLotApplication(object):
  def __init__ (self):

    self.common_settings = None
    self.settings = None
    self.qsettings = None

    self.process = None
    self.io = None

    self.main_gui = None
    self.main_cli = None
    self.main_handler = None

    self.GUIS = None
    self.HANDLERS = None
    self.CLIS = None

    self.gui = None
    self.cli = None
    self.handler = None

def launch_pylot_modules(argv, guiflag):
  u"""
  Steps :

  - import plugin's classes
  - create an unique terminal ProcessHandler and IOHandler
  - create main handler
  - add plugin's handler parts
  - create main CLI using existing main handler
  - add plugin's cli parts
  - parse CLI options to know if GUI must be launched
  if GUI must be launched :
    - create Qt ProcessHandler and IOHandler
    - create main GUI
    - add plugin's gui parts
    - call switchUserLevel, refresh, translate, decorate
    - usual Qt instructions main_gui.show(), app.exec_(), ...
  """

  app = pyLotApplication()


  from pyLot.core import (Path, ENCODING, ProcessHandler, Plugin,
                          uprint, Settings, MainHandler, available_plugins)
  from pyLot.cli import (CliMainManager, pyLotOptionParser)

  help_msg = u"""Usage: pylot-launcher module [options]
  Available modules: %s

  Options:
    -h, --help   show this help message and exit
  """ % (u', '.join(available_plugins(guiflag)))

  if len(argv) < 2 :
    uprint(help_msg, file=sys.stderr)
    sys.exit(1)

  if argv[1] in ('-h', '--help') :
    uprint(help_msg, file=sys.stderr)
    sys.exit(1)

  MODULES = {}
  HANDLERS = {}
  GUIS = {}
  CLIS = {}
  # Import plugin's classes
  modules = argv[1].decode(ENCODING).split(u',')
  for module in modules :
    MODULES[module] = Plugin(module, guiflag)
  modules.sort()

  USERCONF = Path(u'~/.pylot').expanduser()
  userconf_dir = Path(USERCONF, u'plugins_%s' % u'_'.join(modules))
  if not userconf_dir.exists():
    userconf_dir.makedirs()

  settings_path = Path(userconf_dir, u'main_conf.csv')
  settings = Settings(settings_path)
  common_settings = Settings(Path(USERCONF, u'COMMON', u'main_conf.csv'))
  cli_settings = Settings(Path(USERCONF, u'CLI', u'main_conf.csv'))

  # Create explicitly only ProcessHandler because actually, we use default
  # IOHandler of process_handler
  process_handler = ProcessHandler()
  io_handler = process_handler.io

  # Create main handler
  main_handler = MainHandler()

  for module in modules :
    HANDLERS[module] = main_handler.addPlugin(module)
  handler = HANDLERS[modules[0]]

  main_handler.init(io_handler, process_handler)
  main_handler.setUserconf(userconf_dir)

  parser = pyLotOptionParser()
  # Create "main_cli". Equivalent to Qt MainWindow but for command line

  main_cli = CliMainManager(handler=main_handler, parser=parser)
  for module, MODULE in MODULES.items() :
    if MODULE.cli_module :
      # Create CLI using existing handler
      CLIS[module] = main_cli.addPlugin(module, handler=HANDLERS[module])
      CLIS[module].fillGroups()

  try: cli = CLIS[modules[0]]
  except KeyError: cli = None

  main_cli.autoAddGroups()
  main_cli.fillGroups()
  main_cli.translate()

  # Parse command line options
  (options, args) = parser.parse_args()
  # Check if GUI must be launched
  in_console_mode = parser.in_userlist(options, parser.console)

  # Exec treatment corresponding to command line options
  main_cli.runPreOptions(options)
  for cli in CLIS.values():
    cli.runOptions(options)
  main_cli.runOptions(options)

  number_of_guis = 0
  for module in MODULES.values() :
    if module.gui_class :
      number_of_guis += 1

  if not number_of_guis and not in_console_mode :
    uprint(tr_(u'This plugin has no graphical user interface\n'))
    uprint(tr_(u'Uses --help to know available command line options\n'))
    in_console_mode = True

  if not in_console_mode :
    main_handler.readSettings(settings, common_settings)

    from Qt4.QtGui import QApplication
    from Qt4.QtCore import QSettings
    from pyLot.qtgui import (QProcessHandler, GuiMainManager)

    app = QApplication(sys.argv)

    qsettings = QSettings(
        unicode(Path(userconf_dir, u'qt_conf.conf')),
        QSettings.NativeFormat)
    common_qsettings = QSettings(
        unicode(Path(USERCONF, u'COMMON', u'qt_conf.conf')),
        QSettings.NativeFormat)

    # Create Qt IOHandler and ProcessHandler
    process_handler = QProcessHandler()
    process_handler.readSettings(settings, common_settings)
    process_widget = process_handler.getProcessHandlerWidget()

    io_handler = process_handler.io
    status_bar = io_handler.getStatusBarWidget()
    main_handler.init(io_handler, process_handler)

    main_cli.runPreOptions(options)
    for cli in CLIS.values():
      cli.runOptions(options)
    main_cli.runOptions(options)

#    main_handler.switchUserLevel(u'expert')
    # Create MainWindow
    main_gui = GuiMainManager(handler=main_handler,
                              process_widget=process_widget,
                              status_bar=status_bar,
                              dock_mode=main_handler.widget_scheme)

    # Add plugin
    for module_id, module in MODULES.items() :
      if module.gui_class :
        GUIS[module_id] = main_gui.addPlugin(module_id, handler=HANDLERS[module_id])
        alias = tr_(u'Plugin: %s') % module_id.replace(u'_', u' ').capitalize()
        main_gui.autoSetPlugin(module, name=module_id, alias=alias)

    try: gui = GUIS[modules[0]]
    except KeyError: gui = None

    app.gui = gui
    app.main_gui = main_gui
    app.qsettings = qsettings
    app.GUIS = GUIS

    # Read settings
    main_gui.readSettings(qsettings, common_qsettings)

    main_gui.autoAddMenus()
    main_gui.init()
    main_gui.switchUserLevel()
    #main_gui.refresh()
    main_gui.decorate()
    main_gui.translate(force=True)
    main_gui.show()

    app.exec_()


    main_gui.writeSettings(qsettings, common_qsettings)

  if in_console_mode :
    pass
    # save console settings ???
#    process_handler.writeSettings(cli_common_settings, cli_common_settings)
#    main_handler.writeSettings(cli_common_settings, cli_common_settings)
#    cli_common_settings.sync()
  else :
    process_handler.writeSettings(settings, common_settings)
    main_handler.writeSettings(settings, common_settings)

    settings.sync()
    common_settings.sync()

  app.settings = settings
  app.common_settings = common_settings

  app.process = process_handler
  app.io = io_handler

  app.main_cli = main_cli
  app.main_handler = main_handler

  app.HANDLERS = HANDLERS
  app.CLIS = CLIS

  app.cli = cli
  app.handler = handler

  return app

